package com.library.xtype;

import java.lang.ref.WeakReference;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import android.content.Context;
import android.support.annotation.NonNull;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

/**
 * Created by jiangtao on 16/5/21.
 *
 * @author jiang.tao
 * @version 1.0.0
 *
 */
public class NuwaListViewAdapter extends BaseAdapter implements IAdapter, INuwaLifecycle {

    private LayoutInflater mLayoutInflater;
    private NuwaItemPool mNuwaPoolDalegate;
    private List mItemVOs = new ArrayList<>();
    private SparseArray<WeakReference<INuwaItemBinder>> mNuwaViewCache = new SparseArray<>(20);

    /**
     * 使用局部NuwaItemPool
     */
    public NuwaListViewAdapter() {
        this(new NuwaItemPool());
    }

    /**
     * @param itemViewManager itemViewRepository
     */
    public NuwaListViewAdapter(NuwaItemPool itemViewManager) {
        mNuwaPoolDalegate = itemViewManager;
    }

    public NuwaListViewAdapter setNuwaPoolDalegate(NuwaItemPool nuwaPoolDalegate) {
        mNuwaPoolDalegate = nuwaPoolDalegate;
        return this;
    }

    public <T extends INuwaItemBinder> void register(@NonNull Class<T> binder) {
        Type genType = binder.getGenericSuperclass();
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        Class voClazz = (Class) params[0];
        mNuwaPoolDalegate.register(voClazz, binder);
    }

    /**
     * 方法将废弃，请使用
     * @see #register(Class <T>)
     *
     * @param voClazz vo
     * @param binder binder extender INuwaItemBinder
     * @param <T>
     */
    @Deprecated
    public <T extends INuwaItemBinder> void register(@NonNull Class<?> voClazz, @NonNull Class<T> binder) {
        mNuwaPoolDalegate.register(voClazz, binder);
    }

    /**
     * 应用全局的NuwaItemPool
     */
    public void applyGlobalMultiTypePool() {
        Collection<ItemProperty> itemProperties = GlobalNuwaPool.getItemPropertys();
        for (ItemProperty property : itemProperties) {
            register(property.getItemVOClass(), property.getItemBinderClass());
        }
    }

    /**
     * update adapter data
     *
     * @param data data
     */
    @Override
    public void flushData(List data) {
        if (data == null || data.size() == 0) {
            mItemVOs.clear();
            notifyDataSetChanged();
            return;
        }

        mItemVOs = new ArrayList<>(data);
        notifyDataSetChanged();
    }

    /**
     * register data
     * @param data data
     */
    @Override
    public void appendData(List data) {
        if (data == null || data.size() == 0) {
            return;
        }

        mItemVOs.addAll(data);
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return mItemVOs.size();
    }

    @Override
    public Object getItem(int position) {
        return mItemVOs.get(position);
    }

    @Override
    public int getRealCount() {
        return getCount();
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemViewType(int position) {
        return mNuwaPoolDalegate.getItemViewType(getItem(position));
    }

    @Override
    public int getViewTypeCount() {
        return mNuwaPoolDalegate.getTypeCount();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (mLayoutInflater == null) {
            mLayoutInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
        INuwaItemBinder itemView = null;
        final Object itemVO = getItem(position);
        if (convertView == null) {
            // create item view from item view factory
            itemView = mNuwaPoolDalegate.createItemView(parent.getContext(), itemVO);
            // create nullable item view
            if (itemView == null) {
                itemView = new NullableIBinder();
            }
            // create item view
            convertView = itemView.onCreateView(null, parent, mLayoutInflater);

            convertView.setTag(itemView);
        } else {
            itemView = (INuwaItemBinder) convertView.getTag();
        }
        // bind view
        mNuwaViewCache.put(itemView.hashCode(), new WeakReference<>(itemView));
        itemView.onBindView(position, convertView, parent, itemVO);
        return convertView;
    }


    /**
     * clearData and uodate view
     */
    @Override
    public void clearData(){
        if (mItemVOs != null) {
            mItemVOs.clear();
            notifyDataSetChanged();
        }
    }

    /**
     *  remove item and update view
     * @param item remove item
     */
    @Override
    public void removeData(Object item) {
        if (mItemVOs != null && mItemVOs.contains(item)) {
            mItemVOs.remove(item);
            notifyDataSetChanged();
        }
    }

    /**
     *
     * @return all items
     */
    @Override
    public List getAllData() {
        return mItemVOs;
    }

    @Override
    public void onCreate() {
        for(int i = 0, nsize = mNuwaViewCache.size(); i < nsize; i++) {
            WeakReference<INuwaItemBinder> weakView = mNuwaViewCache.valueAt(i);
            final INuwaItemBinder view = weakView.get();
            if (view != null) {
                view.onCreate();
            }
        }
    }

    @Override
    public void onStart() {
        for(int i = 0, nsize = mNuwaViewCache.size(); i < nsize; i++) {
            WeakReference<INuwaItemBinder> weakView = mNuwaViewCache.valueAt(i);
            final INuwaItemBinder view = weakView.get();
            if (view != null) {
                view.onStart();
            }
        }
    }

    @Override
    public void onResume() {
        for(int i = 0, nsize = mNuwaViewCache.size(); i < nsize; i++) {
            WeakReference<INuwaItemBinder> weakView = mNuwaViewCache.valueAt(i);
            final INuwaItemBinder view = weakView.get();
            if (view != null) {
                view.onResume();
            }
        }
    }

    @Override
    public void onPause() {
        for(int i = 0, nsize = mNuwaViewCache.size(); i < nsize; i++) {
            WeakReference<INuwaItemBinder> weakView = mNuwaViewCache.valueAt(i);
            final INuwaItemBinder view = weakView.get();
            if (view != null) {
                view.onPause();
            }
        }
    }

    @Override
    public void onStop() {
        for(int i = 0, nsize = mNuwaViewCache.size(); i < nsize; i++) {
            WeakReference<INuwaItemBinder> weakView = mNuwaViewCache.valueAt(i);
            final INuwaItemBinder view = weakView.get();
            if (view != null) {
                view.onStop();
            }
        }
    }

    @Override
    public void onDestroy() {
        for(int i = 0, nsize = mNuwaViewCache.size(); i < nsize; i++) {
            WeakReference<INuwaItemBinder> weakView = mNuwaViewCache.valueAt(i);
            final INuwaItemBinder view = weakView.get();
            if (view != null) {
                view.onDestroy();
            }
        }
        mNuwaViewCache.clear();
        mNuwaPoolDalegate.destory();
    }
}
